home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-08-05 | 51.6 KB | 1,677 lines |
- Path: solon.com!not-for-mail
- From: seebs@solutions.solon.com (Peter Seebach)
- Newsgroups: comp.lang.c,comp.lang.c.moderated,news.answers
- Subject: comp.lang.c Answers to Infrequently Asked Questions (FAQ List)
- Followup-To: poster
- Date: 1 Apr 1996 15:34:19 -0600
- Organization: Usenet Fact Police (Undercover)
- Approved: seebs@solon.com
- Message-ID: <4jpi4r$6fs@solutions.solon.com>
- NNTP-Posting-Host: solutions.solon.com
- Summary: Questions and Answers.
- X-Last-Modified: April 1, 1996
-
- [Last modified April 1, 1996 by seebs.] [Revision: yes]
-
- [Copyright 1995, 1996 Peter Seebach. All rights reserved, all wrongs reversed.
- Unauthorized duplication and distribution prohibited.]
-
- Certain topics never (well, hardly ever) come up on this newsgroup.
- They are stupid questions, to which the answers are immediately obvious,
- but they would be more fun to talk about than these arcane details of
- loop control.
-
- This article, which is posted yearly, attempts to answer these questions
- definitively, succinctly, and in such a way as to discourage further
- discussion.
-
- 1. Declarations and Initializations
- 2. Structures, Unions, and Enumerations
- 3. Expressions
- 4. Null Statements
- 5. Arrays and Pointers
- 6. Memory Allocation
- 7. Boolean Expressions and Variables
- 8. C Preprocessor
- 9. ANSI/ISO Standard C
- 10. Stdio
- 11. Library Functions
- 12. Floating Point
- 13. Variable-Length Argument Lists
- 14. Lint
- 15. Strange Problems
- 16. Style
- 17. System Dependencies
- 18. Miscellaneous
-
- Questions marked with a leading asterisk (``*'') indicate answers I have seen
- given as real answers, by particularly ignorant posters in comp.lang.c.
- (This added to immortalize a user I recently discovered, whose answers
- to questions sometimes border on the surreal. Name/email address
- available by request.)
-
- Herewith, some infrequently-asked questions and their answers:
-
- Section 1. Declarations and Initializations
-
- 1.1: How do you decide which integer type to use?
-
- A: Use ``short'' when you need to avoid values over 32,767, ``int'' when
- you want to store integers, ``long'' for long numbers (more than 6
- digits), and ``float'' for numbers over 4 billion.
-
- 1.2: What should the 64-bit type on new, 64-bit machines be?
-
- A: int.
-
- 1.3: If I write the code
-
- int i, j;
-
- can I assume that (&i + 1) == &j?
-
- A: Only sometimes. It's not portable, because in EBCDIC, i and j are
- not adjacent.
-
- 1.4: What's the best way to declare and define global variables?
-
- A: In headers; this way, you can get link errors when you include the
- same header twice. Generally, you will have to define a variable
- everywhere you want to use it, and then declare it someplace so
- you know what it is.
-
- 1.5: What does extern mean in a function declaration?
-
- A: It refers to a variable which is not actually in your program. For
- instance,
-
- main() {
- extern int bar;
- printf("%d\n", bar);
- return 0;
- }
-
- will compile without errors because bar is declared as being
- external. (It won't run, though, because you never assign bar a
- value.)
-
- 1.6: I finally figured out the syntax for declaring pointers to
- functions, but now how do I initialize one?
-
- A: With the assignment operator. You were perhaps expecting
- a screwdriver?
-
- 1.7: I've seen different methods used for calling through pointers to
- functions. What's the story?
-
- A: In the old days, when Microsoft first invented C, the syntax for
- calling functions involved more parentheses; this was after their
- market research indicated that most C programmers would be
- coming from a Lisp environment. Later, when Kernighan took
- over the language design (right after AT&T bought Microsoft's
- language technology), he decided to eliminate the parentheses,
- but the old form is still allowed.
-
- You do need the parentheses to call a function with more than
- one argument, for instance,
-
- int (*foo)(char *, ...) = printf;
-
- (*foo)("hello, %s\n", "world!");
-
- needs the parens, but they would not be needed for
-
- foo, "hello, world!\n";
-
- (The ``*'' just means to execute foo, just like the ``*'' on the end
- of an executable filename in ``ls -F''.)
-
- 1.8: What's the auto keyword good for?
-
- A: Declaring vehicles.
-
- 1.9: I can't seem to define a linked list successfully. I tried
-
- typedef struct {
- char *item;
- NODEPTR next;
- } *NODEPTR;
-
- but the compiler gave me error messages. Can't a structure in C
- contain a pointer to itself?
-
- A: Not exactly; it can contain a pointer to another structure of the
- same type. Try:
-
- typedef struct {
- char *item;
- double *next;
- } NODEFAKE;
-
- typedef struct {
- char *item;
- NODEFAKE *next;
- } NODEPTR;
-
- Make sure that sizeof(NODEPTR) == sizeof(double).
-
- This technique is called a ``backwards reference''.
-
- 1.10: How do I enter values using hexadecimal?
-
- A: long ints can be entered using hexadecimal notation; for instance,
-
- long int foo = 07;
-
- sets foo to hex 7.
-
- 1.11: How do I declare an array of N pointers to functions returning
- pointers to functions returning pointers to characters?
-
- A: Well, first you need to know how to declare an array of N
- items of type T - that's
-
- T foo[N];
-
- Now you need to look at how to declare a pointer to function
- returning something, say, an object of type S. That's like this:
-
- S (*bar)();
-
- Now assume that S is ``pointer to function returning pointer to
- char''. We get
-
- (char *) (*)() (*bar)().
-
- So, the whole thing turns out to be (with appropriate parentheses)
-
- (((char)(*))((*)())(((*)((foo)))())([(N))]);
-
- If your compiler complains, break this down into subexpressions.
-
- To call it, just use
-
- foo[i]();
-
- This works because, in C, declaration reflects use, but it's one
- of those weird distorted mirrors.
-
-
- Section 2. Structures, Unions, and Enumerations
-
- 2.1: What is the difference between an enum and a series of
- preprocessor #defines?
-
- A: The enum doesn't require the preprocessor.
-
- 2.2: I heard that structures could be assigned to variables and
- passed to and from functions, but K&R I says not.
-
- A: K&R I was wrong; they hadn't actually learned C very well before
- writing the book. Later, Ritchie got a job at Bell Labs, and worked
- closely with the authors of C, allowing the 2nd edition of the book
- to be much more accurate. (Kernighan already worked at Bell Labs,
- where he helped develop the ``kaw'' programming language, used to
- simulate crows in an international chess tournament.)
-
- 2.3: How does struct passing and returning work?
-
- A: The structures are put into the low part of the VGA card's VRAM.
- They are then removed before the next video update. This is why
- struct passing was not supported for a long time; VGA cards were
- prohibitively expensive.
-
- If you try to pass very large structures on the stack, you may see
- odd screen graphics.
-
- 2.4: Why can't you compare structs?
-
- A: Compare them to what? A summer's day?
-
- 2.5: How can I read/write structs from/to data files?
-
- A: Loop with putchar. Be careful; if your machine uses signed chars
- by default, all of the sign bits in your structure elements will
- be reversed.
-
- 2.6: How can I determine the byte offset of a field within a
- structure?
-
- A: It's generally 4 times the number of members of the structure.
- It may be more or less on some machines.
-
- 2.7: How can I access structure fields by name at run time?
-
- A: foo."name" should work. You may need to overload the . operator,
- which, in turn, may overload your C compiler.
-
- 2.8: Why does sizeof report a larger size than I expect for a
- structure type, as if there was padding at the end?
-
- A: Because there's padding at the end. *DUH*.
-
- 2.9: My compiler is leaving holes in structures, which is wasting
- space and preventing ``binary'' I/O to external data files. Can I
- turn off the padding, or otherwise control the alignment of
- structs?
-
- A: Sure. What you do to eliminate the padding in structures is use
- unions; for intance,
-
- struct foo {
- char c;
- long l;
- char d;
- char e;
- char f;
- };
-
- may cause struct foo to be padded to 12 bytes, rather than the
- correct size of 8. Try
-
- union foo {
- double _d;
- char c, d, e, f;
- long l;
- };
-
- which will be 8 bytes. (The double is for alignment.)
-
- 2.10: Can I initialize unions?
-
- A: Depends. They may go on strike when provoked. Luckily, if your
- program involves air traffic control, the ISO standard guarantees
- that Ronald Reagan will fire any unions that go on strike, and
- replace them with structs, which should be close enough.
-
- 2.11: How can I pass constant values to routines which accept struct
- arguments?
-
- A: Try foo((struct foo) 3).
-
-
- Section 3. Expressions
-
- 3.1: Why doesn't this code:
-
- a[i] = i++;
-
- work?
-
- A: You didn't declare either i or a.
-
- 3.2: Under my compiler, the code
-
- int i = 7;
- printf("%d\n", i++ * i++);
-
- prints 49. Regardless of the order of evaluation, shouldn't it
- print 56?
-
- A: No. The only logical answer would be 81 - two postfix ++'s are
- automatically converted to prefix.
-
- 3.3: I've experimented with the code
-
- int i = 2;
- i = i++;
-
- on several compilers. Some gave i the value 2, some gave 3, but
- one gave 4. I know the behavior is undefined, but how could it
- give 4?
-
- A: Because i is 2, the loop is executed twice.
-
- 3.4: People keep saying the behavior is undefined, but I just tried
- it on an ANSI-conforming compiler, and got the results I
- expected.
-
- A: They were probably wrong. Flame them mercilessly. Be sure before
- you do that your compiler is really* ANSI conforming, though. If
- it turns out you were wrong, they get a legal claim on your first-born.
-
- 3.5: Can I use explicit parentheses to force the order of evaluation
- I want? Even if I don't, doesn't precedence dictate it?
-
- A: No. To force order of evaluation, you must threaten it. Take the
- comma operator hostage. Using it, you can force the other operators
- to do what you want.
-
- 3.6: But what about the &&, ||, and comma operators?
- I see code like ``if((c = getchar()) == EOF || c == '\n')'' ...
-
- A: As noted, once you've captured the comma operator, the others
- become docile.
-
- 3.7: If I'm not using the value of the expression, should I use i++
- or ++i to increment a variable?
-
- A: ++i. Only losers and idiots use i++. This is different if your
- native language would idiomatically use ``i increment'', but in
- English and related languages, you must use ``++i''. Note that
- a modern program must use both, dependent on the current locale.
-
- 3.8: Why is i = ++i undefined?
-
- A: Because it is unclear whether it is shorthand for
-
- i = 42;
-
- or
-
- i = (char *) "forty two";
-
- Given the ambiguity, the standards committee decided to leave it
- undefined.
-
-
- Section 4. Null Statements
-
- 4.1: What is this infamous null statement, anyway?
-
- A: A null statement is an expression statement consisting solely
- of the terminating semicolon. The optional expression is dropped.
- It can be distinguished from any other statement by byte count
- or study of side-effects.
-
- 4.2: How do I ``get'' a null statement in my programs?
-
- A: In ANSI C, there are six types of statements; labeled statements,
- compound statements, expression-statements, selection statements,
- iteration statements, and jump statements. All of them, except
- the jump and expression statments, are defined in terms of optional
- preceeding text, and other statements. The jump statements are
- never null statements. An expression statement is considered to
- be ``a null statement'' if the optional expression part of it has
- been left out. A null statement can appear on its own, or (most
- frequently) as the statement body of an iteration statement. These
- two null statements are equivalent, though neither of them is
- equivalent to any non-null statement. [*]
-
- You may accidentally get a null statement by deleting the body of
- a non-null statement.
-
- [*] Actually, they are functionally equivalent to a large set of
- non-null statements, namely, those with no side-effects. However,
- the FDA has yet to approve any such, as their lack of side effects
- is conjectured, and not clinically proven. This applies only to
- the ANSI standard, and not the ISO standard, as the FDA has no
- jurisdiction outside the U.S.
-
- 4.3: Is there more than one null statement?
-
- A: Sort of. You can use
- ;
- or
- 0;
- or
- 1;
- - they will all act like a null statement. Only the first is
- a ``true'' null statement (all bits zero). They are basically
- equivalent. Note that (void *) 0; is a null statement of type
- pointer to void, for instance.
-
- 4.4 But I thought { } was a null statement!
-
- A: No. { statement-list[opt] } is a compound statement. An empty
- block is not the same as a null statement, however, although it
- can be used in many of the same places. It's really a null
- block. (You can convert it with a cast, but it's not directly
- compatible. For instance, you can't use a null block as one
- of the controlling statements of a for loop.)
-
- 4.5 I use the statement
- #define NULLSTMT(F) (F) ;
- to allow me to cast a null statement to an appropriate type.
-
- A: This trick, though popular in some circles, does not buy much.
- The resulting code is illegal, and will not compile. This (in
- the author's opinion) outweighs any arguable type consistency.
- It may be more common in industrial code. If it becomes common
- practice, C++ will probably legalize it.
-
- 4.6 I use the statement
- #define NULLSTMT(F) (F) 0;
- to allow me to cast a null statement to an appropriate type.
-
- A: This trick will likely work, but think: what does it really buy
- you? Mostly, it will indicate to even the most casual observer
- that you are shakey on the concept of null statements, making it
- harder for them to check your code.
-
- 4.7: But wouldn't it be better to use ``;'' (rather than ``0;'') in case
- the value of 0 changes, perhaps on a machine with nonzero
- no-op instructions?
-
- A: No. The ``0'' of ``0;'' is not evaluated as an instruction, rather,
- it is just ignored. The advantages of ``;'' over ``0;'' have only to
- do with poor optimizers and savings of keystrokes.
-
- 4.8: Is a null statement a null pointer?
-
- A: No. A null pointer is a pointer where all of the address bits
- are zero (no matter what the segment bits are), and can be
- obtained by typing '(char *) (int) 0'. A null statement is
- not a pointer to anything. They are not interchangeable, although
- you can combine them to get an effectively-null statement, such
- as
-
- NULL;
-
- This does not buy you anything.
-
- 4.9: I'm still confused. I just can't understand all this null
- statement stuff.
-
- A: Follow these two simple rules:
-
- 1. When you don't want to do anything in source code, don't
- write it.
-
- 2. If you need a null statement to round out an expression,
- use an unadorned ``;'' to provide it.
-
- 3. Send large donations, checks, and money orders to the
- author of the FAQ, or the moderator of the group, whichever
- you prefer. Then, cross the top question off the FAQ,
- answer the question at the bottom, and mail it to three
- people. Within two weeks, you will receive 729 answers
- to various questions! Do not break the chain; Emily
- Postnews broke the chain, and now no one listens to her.
-
-
- Section 5. Arrays and Pointers
-
- 5.1: I had the definition char a[6] in one source file, and in
- another I declared extern char a[]. Why did it work?
-
- A: The declaration extern char a[] simply matches the actual definition.
- The type ``array-of-type-T'' is the same as ``array-of-type-T.''
- Go ahead and use extern char a[]. (For greater portability, use
- it in both files, not only in one of them.)
-
- 5.2: But I heard that char a[] was different from char a[6].
-
- A: This is true. However, the declaration a[] is compatible with the
- definition a[6].
-
- 5.3: So what is meant by the ``equivalence of pointers and arrays'' in
- C?
-
- A: Very little.
-
- 5.4: Then why are array and pointer declarations interchangeable as
- function formal parameters?
-
- A: Classism. We consider arrays ``second class objects''. They don't
- vote, and they get treated as pointers. Additionally, they're
- merely objects, not citizens. Marx wrote about this a lot.
-
- 5.6: Why doesn't sizeof properly report the size of an array which is
- a parameter to a function?
-
- A: Part of the ANSI conspiracy to restrict people to passing pointers;
- this was undertaken after the first discovery that passing large
- arrays recursively could cause crashes. Since then, with the passing
- of MS-DOS, it has become a non-issue; since all serious machines
- have virtual memory, you can pass as much data as you want on the
- stack without detectable problems.
-
- 5.7: Someone explained to me that arrays were really just constant
- pointers.
-
- A: Cool. Someone I know says he saw Elvis in a local bar.
-
- 5.8: Practically speaking, what is the difference between arrays and
- pointers?
-
- A: About the difference between alcohol and marijuana; they have
- different characteristics, and that's not a problem if you don't
- mix them too carelessly.
-
- 5.9: I came across some ``joke'' code containing the ``expression''
- 5["abcdef"] . How can this be legal C?
-
- A: It was added to allow people to avoid the character constant
- 'f' which may not be available on some systems. (Actually, it's
- a side-effect of the equivalence of arrays and pointers.)
-
- 5.10: How would I initialize an entire array from standard input?
-
- A: You have to use a loop. For instance, the following code reads
- the numbers zero through 99 into the array a.
-
- for (i = 0; i < 100; ++i)
- a[i] = (scanf, ("%d", i));
-
- Make sure to include <stdio.h>, or this may not work.
-
-
- Section 6. Memory Allocation
-
- 6.1: Why doesn't this fragment work?
-
- char *answer
- printf("Type something:\n");
- gets(answer);
- printf("You typed \"%s\"\n", answer);
-
- A: The semicolon after ``answer'' is missing.
-
- 6.2: I have a function that is supposed to return a string,
- but when it returns to its caller, the returned string is
- garbage.
-
- A: You probably returned a pointer to a local array. That
- doesn't work. Try using a temporary file, instead. For instance:
-
- char *getstr(void) {
- FILE *fp = tmpfile();
-
- fputs(gets(NULL), fp);
- return (char *) fp;
- }
-
- 6.3: Why does some code carefully cast the values returned by malloc
- to the pointer type being allocated?
-
- A: In interrupt-riddled code, it may be necessary to cast values to
- force the CPU to resolve pointer types.
-
- 6.4: You can't use dynamically-allocated memory after you free it,
- can you?
-
- A: Yes. However, what happens when you do is not clearly defined.
-
- 6.5: How does free() know how many bytes to free?
-
- A: Interrupt 41h. On macs, amigas, and other ``big-endian'' processors,
- that would be interrupt 14h; be wary of portability problems.
-
- 6.6: So can I query the malloc package to find out how big an
- allocated block is?
-
- A: Not exactly; because the objects are dynamically allocated, their
- size can change at run time, so this will not be reliable. If you
- restrict your allocation to allocating sizeof(void *) bytes at a
- time, you will find that you can use sizeof() to get the size of a
- block, in the obvious way.
-
- 6.7: I'm allocating structures which contain pointers to other
- dynamically-allocated objects. When I free a structure, do I
- have to free each subsidiary pointer first?
-
- A: No. You just have to keep track of them somewhere else also.
-
- 6.8: Was Proust's masterwork, _A Remembrance of Things Past_, the
- basis for the C library's allocation scheme, based largely on
- contextual analysis?
-
- A: The standard does not specify an allocation scheme; the famous
- author the allocation scheme is based on is implementation
- specified. Proust is a common choice, however.
-
- 6.9: I have a program which mallocs but then frees a lot of memory,
- but memory usage (as reported by ps) doesn't seem to go back
- down.
-
- A: You're probably not freeing the memory completely. Try replacing
-
- free(foo);
-
- with
-
- free(foo);
- free(foo);
- free(foo);
-
- in case the first free() frees the memory only partially.
- (Unix wizards may recognize the parallel with syncing
- three times before rebooting.)
-
- Alternatively,
- free(foo) + 4; may free the remaining four bytes. (Before using
- this, make sure realloc(foo, 0) returned 4).
-
-
- Section 7. Boolean Expressions and Variables
-
- 7.1: What is the right type to use for boolean values in C? Why
- isn't it a standard type? Should #defines or enums be used for
- the true and false values?
-
- A: int (*)(int, char **) makes a good boolean type. You can use
- ``main'' for true, and ``exit'' for false. On some compilers, you
- may need to cast exit() to an appropriate type.
-
- 7.2: Isn't #defining TRUE to be 1 dangerous, since any nonzero value
- is considered ``true'' in C? What if a built-in boolean or
- relational operator ``returns'' something other than 1?
-
- A: Very good! For instance, one program I saw used
-
- #define TRUE(x) ((x) & 0x100)
-
- for compatability with a specific release of a FORTRAN compiler,
- which used 0 for .FALSE. and 256 for .TRUE. - this allowed them to
- change their code with every new release of the FORTRAN compiler,
- and kept them alert to changes. This has no relationship to
- the boolean or logical operators in C, which always return 0 or 1.
-
- 7.3: What is truth?
-
- A: It is not a saffron-robed monk, pissing in the snow.
-
-
- Section 8. C Preprocessor
-
- 8.1: How can I use a preprocessor #if expression to tell if a machine
- is big-endian or little-endian?
-
- A: #ifdef __BIG_ENDIAN should work on all known machines; Borland
- defines it.
-
- 8.2: I've got this tricky processing I want to do at compile time and
- I can't figure out a way to get cpp to do it.
-
- A: Poor baby.
-
- 8.3: How can I list all of the pre-#defined identifiers?
-
- A: #define __ALL_CPP_IDS - put this in a source file, and run it
- through your C preprocessor.
-
- 8.4: How can I write a cpp macro which takes a variable number of
- arguments?
-
- A: #define add(x) (x)
- #define add(x, y) (x + y)
- #pragma induction add
-
- 8.5: Shouldn't the following code:
-
- #define ROSE 1
- #define CHRYSANTHEMUM 2
- #define RHODODENDRON 3
- #define WATER_LILY 4
-
- printf("%d\n", CHRYSATHNEMUM);
-
- print ``2''?
-
- A: You misspelled CHRYSANTHEMUM. Use abbreviations for long flower
- names in C code.
-
-
- Section 9. ANSI C
-
- 9.1: What is the ``ANSI C Standard?''
-
- A: A whiny bunch of lusers who haven't written as many books as
- Herbert Schildt.
-
- 9.2: How can I get a copy of the Standard?
-
- A: ftp ftp.borland.com.
-
- 9.3: Does anyone have a tool for converting old-style C programs to
- ANSI C, or vice versa, or for automatically generating
- prototypes?
-
- A: A router helps, but your best bet is still the band saw. Quick,
- efficient, and powerful.
-
- 9.4: I'm trying to use the ANSI ``stringizing'' preprocessing operator
- # to insert the value of a symbolic constant into a message, but
- it keeps stringizing the macro's name rather than its value.
-
- A: This is because ``3'' is not a legal integral constant in C - it's
- a string constant.
-
- 9.5: I don't understand why I can't use const values in initializers
- and array dimensions, as in
-
- const int n = 7;
- int a[n];
-
- A: Because you're not using C++.
-
- 9.6: What's the difference between ``char const *p'' and
- ``char * const p''?
-
- A: One `` '' character. There are some trivial differences having
- to do with the distinction between a pointer to a constant, and
- a constant pointer, but since you can cast either to a
- (char *) it hardly matters.
-
- 9.7: Can I declare main as void, to shut off these annoying ``main
- returns no value'' messages? (I'm calling exit(), so main
- doesn't return.)
-
- A: Certainly. You can also declare it as double. It may not
- compile, or it may crash, but who cares? No lousy bunch of
- whining lusers is going to tell *you* what to do.
-
- 9.8: Why does the ANSI Standard not guarantee more than six monocase
- characters of external identifier significance?
-
- A: Because none of the members of the committee had names over
- six letters, or in which letters other than the first were
- capitalized.
-
- 9.9: What is the difference between memcpy and memmove?
-
- A: memmove moves memory, and memcpy copies it. memmove may
- not be supported on machines without internal robot arms. Do not
- use memmove while the machine is powered up - you can destroy
- your memory.
-
- 9.10: Why won't the Frobozz Magic C Compiler, which claims to be ANSI
- compliant, accept this code? I know that the code is ANSI,
- because gcc accepts it.
-
- A: The Frobozz Magic Company lies through its teeth. Consider:
- does Flood Control Dam #3 actually control floods? Didn't
- think so. The wands are excellent for making useless via
- casts of Float, though.
-
- 9.11: Why can't I perform arithmetic on a void * pointer?
-
- A: You're too big and clumsy. When you try to push the numbers
- together, you lose your balance. Perhaps you should get some
- angels from the rave over on pin 3.
-
- 9.12: What are #pragmas and what are they good for?
-
- A: They are useful ways to eliminate compiler features which are not
- helpful to your goals; contrast #utility, which introduces useful
- compiler features, and #absolutist, which introduces those compiler
- features believed to be right. #relativist is supported by some
- compilers.
-
- 9.13: What does ``#pragma once'' mean? I found it in some header files.
-
- A: It means that your program will only run once; it's used to create
- ``crippled demos''.
-
- 9.14: People seem to make a point of distinguishing between
- implementation-defined, unspecified, and undefined behavior.
- What's the difference?
-
- A: There isn't really one; people just enjoy flaming over nits.
- (To be technical, one has a hyphen, one has a space, and one
- is a single word.)
-
- 9.15: Is C an acronym?
-
- A: Yes, it stands for ``C''. It's another of those funky recursive
- acronyms.
-
-
- Section 10. Stdio
-
- 10.1: What's wrong with this code:
-
- char c;
- while((c = getchar()) != EOF)...
-
- A: You forgot to include space for the terminating NUL character,
- so the compiler can't find the end of c without overwriting
- other memory. In all probability, after the user types ``n<return>'',
- your code will look like
-
- char cn
- while((c = getchar()) != EOF)...
-
- which won't compile.
-
- Also, the ellipsis is not legal outside of function protoypes.
-
- Try
-
- char c[2]; /* include space for terminating NUL */
- while ((c = getchar()) != EOF)
- ;
-
- (Note the use of the null statement to absorb the NUL. See
- Section 4 for more explanation.)
-
- 10.2: How can I print a ``%'' character in a printf format string? I
- tried ``\%'' but it didn't work.
-
- A: Break the '%' sign out. i.e.,
- fprintf("foo " "%" "%d\n", foo);
-
- Alternatively, try
-
- sprintf("o" "/" "o") to get a "%".
-
- The astute reader will notice that the latter example uses sprintf,
- and the former fprintf - this is because sprintf() works by
- characters, or strings, while fprintf (``fast printf'') works on files.
-
- 10.3: Why doesn't the code scanf("%d", i); work?
-
- A: You need to do this a bit differently; you should always check for
- the return from scanf, so try something like
- i = 1;
- if ((scanf, "%d", i) == 1)
-
- to make sure you're reading correctly. (The assignment to i is
- so that, if scanf fails, you still have a legal value in i.)
-
- 10.4: Once I've used freopen, how can I get the original stdout (or
- stdin) back?
-
- A: Call main() - the environment will be restored.
-
- 10.5: Why won't the code
-
- while(!feof(infp)) {
- fgets(buf, MAXLINE, infp);
- fputs(buf, outfp);
- }
-
- work?
-
- A: Because the end of file character is not detected on files named
- ``infp''. (Introverted-iNtuitive-Feeling-Perceptive, that is.) Also,
- it may be that the file was opened in text mode, where an end of
- file is read as a capital 'Z' on most machines, and feof() only
- looks for 'control Z'.
-
- 10.6: Why does everyone say not to use gets()?
-
- A: Because they're trying to spoil your fun. gets() can make an
- otherwise droll and predictable program a lot more exciting.
-
- 10.7: Why does errno contain ENOTTY after a call to printf?
-
- A: Because stdout is not a mammal.
-
- 10.8: My program's prompts and intermediate output don't always show
- up on the screen, especially when I pipe the output through
- another program.
-
- A: Have you turned your monitor on? If not, try hitting the ``PrtSc''
- key, which will re-enable the electron guns.
-
- 10.9: How can I read one character at a time, without waiting for the
- RETURN key?
-
- A: Ask the user to press enter after hitting a single character.
-
- 10.10: People keep telling me that getch() is not standard, but my C
- compiler has it. Are they wrong?
-
- A: They've been programming more than ten years. You haven't. Draw
- your own conclusions. That's right! They hadn't noticed it.
- No doubt their compilers have it too, and its behavior is identical
- everywhere else in the world, also. That would explain everything.
-
- 10.11: What does it matter that getch() isn't standard; it works, doesn't
- it?
-
- A: Well, that would depend on the definition you're using for ``works''.
-
- 10.12: I tried to port some code from a PC to a unix machine, and now it
- crashes immediately on startup. It isn't using getch() - it's
- reading directly from the keyboard. How can this be wrong?
-
- A: The chances are you forgot to run the Unix linker; currently your
- code is linked to your PC hardware, and won't run anywhere else
- until it's linked to the new hardware. It may also need to be linked
- to someone with a brain.
-
- 10.13: How can I redirect stdin or stdout to a file from within a
- program?
-
- A: execlv("main()" "> file", argv);
-
- 10.14: How can I recover the file name given an open file descriptor?
-
- A: You will have to search the filesystem for files of the same size
- as the file you're reading, and compare information in them to
- find the file you're working on.
-
- 10.15: How do I open Flood Control Dam #3?
-
- A: PUSH THE YELLOW BUTTON.
- TURN THE BOLT WITH THE WRENCH.
- (You must have the wrench, first.)
-
-
- Section 11. Library Subroutines
-
- 11.1: How can I convert numbers to strings (the opposite of atoi)? Is
- there an itoa function?
-
- A: There's frequently an itoa function. Better yet, write your own;
- it'll be good practice. On some implementations, (char *) x;
- will convert x to a string.
-
- 11.2: How can I get the current date or time of day in a C program?
-
- A: fprintf(stderr, "please enter the current time and date...");
- fflush(stderr);
- gets(stdin);
-
- 11.3: I need a random number generator.
-
- A: Count errors in Herbert Schildt's C books. No one has detected
- any consistent pattern.
-
- 11.4: How can I get random integers in a certain range?
-
- A: random(n) returns random numbers between n and INT_MAX.
-
- 11.5: Each time I run my program, I get the same sequence of numbers
- back from rand().
-
- A: This is so your results will be reproducible.
-
- 11.6: I need a random true/false value, so I'm taking rand() % 2, but
- it's just alternating 0, 1, 0, 1, 0...
-
- A: That seems pretty random to me.
-
- 11.7: I need some code to do regular expression matching.
-
- A: So do I. Let me know if you find some.
-
- 11.8: I read through the standard library, but there's no function
- to multiply two floating point numbers! Help!
-
- A: Many C compilers offer an extension ``mult'' to do just this.
- If your compiler doesn't, just hang tight; ANSI is likely to
- add it in the next revision.
-
- For now, you can try
-
- float mult(float m, n)
- {
- float i = 0, j = 0;
- for (i = 0; i < n; ++i)
- j += m;
- return j;
- }
-
- which is fine as long as n is an integer.
-
- 11.9: How do I get past the snake?
-
- A: Release the bird. You will have to drop the rod to get the
- bird in the cage.
-
-
- Section 12. Floating Point
-
- 12.1: My floating-point calculations are acting strangely and giving
- me different answers on different machines.
-
- A: One of the machines is probably a Pentium. Scrap it and get a real
- machine.
-
- 12.2: I'm trying to do some simple trig, and I am #including <math.h>,
- but I keep getting ``undefined: _sin'' compilation errors.
-
- A: You forgot to define the sin() function. Most math texts should
- cover it in some detail. The easiest way to fix this should be:
-
- double sin(double x) {
- return sqrt(1 - cos(x) * cos(x));
- }
-
- Warning: You *must not* declare this function as ``extern'', or
- you will still have link problems.
-
- 12.3: Why doesn't C have an exponentiation operator?
-
- A: It does. It looks like the multiplication operator, but you use
- it more. For instance, the C way of expressing ``x squared'' is
- ``x*x''. ``x cubed'' would be ``x*x*x''. Easy, isn't it?
-
- 12.4: How do I round numbers?
-
- A: Multiply by 10. _Numerical Recipies in C_ has a section on this,
- but there's reputedly a bug in their algorithm.
-
- 12.5: How do I test for IEEE NaN and other special values?
-
- A: Using an electron microscope; the patterns are obvious once you
- know them.
-
- 12.6: I'm having trouble with a Turbo C program which crashes and says
- something like ``floating point formats not linked.''
-
- A: Turbo C is notoriously buggy. Get a compiler with floating
- point support.
-
- 12.7: What is so ``unsafe'' about floating point?
-
- A: Have you tried EXAMINE STICK? The stick has a sharp point, which
- punctures the raft, which no longer floats. Don't bring the stick
- into the raft with you.
-
- 12.8: Which is larger, ``2'' or ``2.0''?
-
- A: _Numerical Recipes in C_ has a function for comparing two values
- to see which is greater. It may have a slight bug, where it would
- report incorrect results if the numbers differ by less than
- FLOAT_MAX / INT_MAX.
-
- 12.9*: When I try to compile the following code, I get the error ``invalid
- use of floating point'', what does this mean?
-
- x=663608941*y%pow(2,32);
-
- A: Remember that * is the indirection operator, as well as the
- multiplication operator; try putting spaces before and after the
- ``*'' so the compiler knows what you mean. Do the same with the %
- operator.
-
- 12.10*: How can I copy a float into a string?
-
- A: strcpy(string_var, float_var);
-
- 12.11: What are float variables, anyway?
-
- A: The term ``float variable'' is actually redundant; they are simply
- variables whose value can ``float'' during execution. For instance:
-
- float f, g = 3;
-
- f = g; /* f ``floats'' to g */
-
- Easy!
-
-
- Section 13. Variable-Length Argument Lists
-
- 13.1: How can I write a function that takes a variable number of
- arguments?
-
- A: By declaring it with a variable number of arguments in the
- prototype. Use only the arguments declared at any given
- time.
-
- 13.2: How can I write a function that takes a format string and a
- variable number of arguments, like printf, and passes them to
- printf to do most of the work?
-
- A: Redefine printf; the call to ``printf'' inside yours will be
- resolved to the library version, because the C language doesn't
- allow recursion.
-
- 13.3: How can I discover how many arguments a function was actually
- called with?
-
- A: _args is an external integer constant. It evaluates to three
- times the number of arguments the current function was called
- with. You can then look at
- _argdata[args] to get the address of the last arg,
- _argdata[args - 1] to get the size of the last arg, and
- _argdata[args - 2] to get the type of the last arg (as an int).
-
- N.B. You *MUST* not refer to _args or _argdata between
- the ()'s of a function call; their value will be
- indeterminate. Use temporary storage.
-
- 13.4: Why doesn't
-
- printf("hello, ", "world!", '\n');
-
- work? I thought printf() took a variable number of arguments.
-
- A: It will probably work some of the time; the number of arguments
- used by printf() may vary, as it is a variadic function.
-
-
- Section 14. Lint
-
- 14.1: I just typed in this program, and it's acting strangely. Can
- you see anything wrong with it?
-
- A: Yes. There's too much lint in it. You should get a shop vac.
-
- 14.2: How can I shut off the ``warning: possible pointer alignment
- problem'' message lint gives me for each call to malloc?
-
- A: Don't run lint. Alternatively, provide a prototype of
- ``extern double * malloc()'' to make the return from malloc()
- be more strongly aligned.
-
- 14.3: Where can I get an ANSI-compatible lint?
-
- A: You may wish to check your spouse's navel occasionally,
- especially if your spouse works for a standards committee.
-
- 14.4: What does LINT stand for, anyway?
-
- A: Lexeme Interpreter aNd Tester.
-
-
- Section 15. Strange Problems
-
- 15.1: Something really strange happened when I ran this code!
-
- A: No, it didn't.
-
-
- Section 16. Style
-
- 16.1: Here's a neat trick:
-
- if(!strcmp(s1, s2))
-
- Is this good style?
-
- A: Not really; it's too similar to
-
- if (!strncmp(s1, s2))
-
- which invokes undefined behavior, so it might be confusing.
-
- 16.2: Here's an even neater trick:
-
- volatile int True_Tester = 3;
- #define TRUE (!True_Tester == !True_Tester)
- #define FALSE ((!TRUE) != (!TRUE))
-
- #define STR_DISSIMILAR(x, y) (strcmp((x), (y)) != FALSE)
-
- Isn't this cool?
-
- A: Very impressive. The volatile int type assures that even seemingly
- redundant calculations involving True_Tester will be performed,
- making sure that if the compiler's ANSI-compliant values of 0 for
- false and 1 for true vary during runtime, your program will detect
- it - and producing meaningful error messages if this change occurs
- during a boolean computation! Similarly, the STR_DISSIMILAR
- macro allows you to make quite clear what the real effects of
- strcmp() are.
-
- However, you must be careful; if this code is included twice, it
- may produce errors, due to the multiple definitions of the
- ``True_Tester'' variable. You may wish to declare it ``extern'' (See
- question 1.5).
-
- 16.3: What's the best style for code layout in C?
-
- A: There are many systems of indentation advocated, but all of them
- have the same basic flaw; they will mislead the reader when the
- actual code logic does not follow the indentation. It is better to
- avoid indentation entirely, so the reader will not be misled.
-
- 16.4: Is goto a good thing or a bad thing?
-
- A: Yes.
-
- 16.5: No, really, should I use goto statements in my code?
-
- A: Any loop control construct can be written with gotos; similarly,
- any goto can be emulated by some loop control constructs and
- additional logic.
-
- However, gotos are unclean. For instance, compare the
- following two code segments:
-
- do { foo();
- foo(); if (bar())
- if (bar()) goto SKIP;
- break; baz();
- baz(); quux();
- quux();
- } while (1 == 0); SKIP:
- buz(); buz();
-
- Note how the loop control makes it quite clear that the statements
- inside it will be looped on as long as a condition is met, where the
- goto statement gives the impression that, if bar() returned a nonzero
- value, the statements baz() and quux() will be skipped.
-
- 16.6: What's this ``white space'' I keep hearing about?
-
- A: White space is a racist, segregational term. Implicitly, ``dark''
- or ``colored'' space (i.e., the '_' character) is not good enough
- to separate tokens. More interestingly, the white space characters
- keep the other tokens apart. They say it's for parsing, but
- there's ample evidence the goal of white space is to keep the
- other characters from ``taking over'' the program. This is
- disguised by the description of C as ``white space insensitive'' -
- a simple ploy for sympathy.
-
-
- Section 17. System Dependencies
-
- 17.1: How can I read a single character from the keyboard without
- waiting for a newline?
-
- A: Try 'stty eol ^M' to wait for a carriage return.
-
- 17.2: How can I find out if there are characters available for reading
- (and if so, how many)? Alternatively, how can I do a read that
- will not block if there are no characters available?
-
- A: The buffer is normally at ``&main - 0100''. Lower if you have more
- than 256 characters of typeahead.
-
- 17.3: How can I clear the screen? How can I print things in inverse
- video?
-
- A: You can clear the screen by sending several formfeed characters.
- Additionally, some operating systems (like NetBSD) support a
- feature called ``whiteouts''.
-
- 17.4: How do I read the mouse?
-
- A: Flip it over, put on your reading glasses.
-
- 17.5: How can my program discover the complete pathname to the
- executable file from which it was invoked?
-
- A: By asking the user.
-
- 17.6: How can a process change an environment variable in its caller?
-
- A: Only by force. Example code for Unix:
-
- memmove(getppid() + getenv(NULL), getpid() + getenv(NULL),
- sizeof(environ);
-
- 17.7: How can I check whether a file exists? I want to query the user
- before overwriting existing files.
-
- A: Time an attempt to truncate it to zero length; if it takes more than
- 20-30 ms, the file existed. The exact values will depend on the
- system and the load; before testing, create several large files
- and time attempts to truncate them, for calibration.
-
- 17.8: How can I find out the size of a file, prior to reading it in?
-
- A: There are two good ways:
-
- 1. Vernier calipers work well.
-
- 2. mmap() the file, then use sizeof().
-
- 17.9: I tried to use the second strategy above. I used mmap() to map
- stdin, then tried to use sizeof. But, when my user is about to
- write something very long, mmap() fails! How can I prevent this?
-
- A: mmap() only 1k at a time, then, when you've read the first kilobyte
- of your input, use
- memmove(mmapped_addr, mmapped_addr + 1024, 1024);
- to move in the next kilobyte of data.
-
- 17.10: How can I implement a delay, or time a user's response, with
- sub-second resolution?
-
- A: Time writes of large files to disks; then you can wait for a certain
- amount of time by writing a certain amount of data, and time a
- response by how much you could write before the response arrived.
-
- You may need to delete spare or unneccessary files to do this;
- for best results, use a loop like the following to eliminate
- temporary files:
-
- d = opendir(s);
- while (r = readdir(d)) {
- /* remove files matching tmpnam's return, which is
- * the temporary file name. */
- if (strcmp(d->d_name, tmpnam())) {
- remove(d->d_name);
- }
- }
- closedir(d);
-
- 17.11: How can I read in an object file and jump to routines in it?
-
- A: fopen and goto.
-
- 17.12: How can I invoke an operating system command from within a
- program?
-
- A: Ask the user to open a new shell. The best way to do this is
-
- system("echo Please open a new shell now.");
- sprintf(cmdstring, "echo Enter the command '%s' in it.", cmd);
- system(cmdstring);
-
- This will not work if you haven't declared cmdstring properly.
-
- 17.13: How can I ensure objects of my class are always created via
- ``new'' rather than as locals or global/static objects?
-
- A: Read the C++ FAQ.
-
-
- Section 18. Miscellaneous
-
- 18.1: What can I safely assume about the initial values of variables
- which are not explicitly initialized? If global variables start
- out as ``zero,'' is that good enough for null pointers and
- floating-point zeroes?
-
- A: They're always zero.
-
- 18.2: How can I write data files which can be read on other machines
- with different word size, byte order, or floating point formats?
-
- A: The traditional solution, pioneered by Microsoft, is to sell enough
- copies of your proprietary, slow, and limited software that everyone
- else supports your formats.
-
- 18.3: How can I insert or delete a line (or record) in the middle of a
- file?
-
- A: Using fcntl(), lock the line or record in the file exclusively.
- Now, using another thread, read the file, at each byte, trying
- to write that byte back. Whenever you succeed, write that byte
- into another file. Then copy the new file over the old file,
- releasing the lock first.
-
- 18.4: How can I return several values from a function?
-
- A: Code like this ought to work.
-
- long int foo() {
- return 2L +3; /* returns both values */
- }
-
- 18.5: If I have a char * variable pointing to the name of a function
- as a string, how can I call that function?
-
- A: eval(s);
-
- Now all you need to do is write eval().
-
- 18.6: I seem to be missing the system header file <math.h>. Can
- someone send me a copy?
-
- A: A lot of people claim that it is useless to send people headers
- from other machines. Not so! It can be informative, and can
- show you a lot about how blatantly stupid your request was,
- although it can't show you anything you wouldn't have known in
- an instant had you thought before posting.
-
- Of course, we'd be happy to send you the header files...
-
- ----cut here----
- /* math.h rev 7.0b (3/7/95) */
-
- /* RCS log: #log% - can anyone tell me why this doesn't work?
- * - joe, 2/12/93
- */
-
- /*
- * Copyright 1995 Berserkley Software Systems && Analytic Overdrive
- */
-
- /* Parts of this header, including in particular the second and
- * third clauses of the first sentance of the fourth comment, were
- * based on copyright agreements from other sources, including
- * Xerox corporation.
- */
-
- /*
- * math.h - math related macros and headers
- */
-
- #ifndef _MATH_H
- #define _MATH_H
-
- /*
- * global data and definitions
- */
-
- #ifdef __LITERAL_BIBLICAL_FUNDEMENTALISM
- #define PI 3.0 /* 1 Kings 7:23 */
- #endif
-
- /*
- * common (portable) structures and functions
- */
-
- /*
- * machine specific data
- */
- #include <machine/math.h>
-
- #endif /* _MATH_H // prevent multiple inclusion by using C++ comments*/
- ----cut here----
-
- (Morons.)
-
- 18.7: How can I call FORTRAN (C++, BASIC, Pascal, Ada, LISP, perl) functions
- from C? (And vice versa?)
-
- A: DO CALL FORTRAN; fortran();
- __LINE__ BASIC; basic();
- sub pascal; pascal();
- (((((lisp))))) lithp(); [*]
- &perl_c; perl():
-
- (You can't call Ada from C; it's unsafe.)
-
- [*] C is pass by value, of course.
-
- 18.8: Does anyone know of a program for converting Pascal or FORTRAN
- (or LISP, Ada, awk, ``Old'' C, ...) to C?
-
- A: Nope. However, the psychic friends network may have a lead. And
- they're not just a psychic, they're also a friend.
-
- 18.9: Is C++ a superset of C? Can I use a C++ compiler to compile C
- code?
-
- A: C++ is a superset of something, we're not sure what. You can use
- a C++ compiler to compile C code, but the results may surprise you.
-
- 18.10: Where can I get copies of all these public-domain programs?
-
- A: From ftp.microsoft.com. Some of the code may look copyrighted;
- don't worry! The small companies that wrote it in the first place
- are not available for comment.
-
- 18.11: When will the next International Obfuscated C Code Contest
- (IOCCC) be held? How can I get a copy of the current and
- previous winning entries?
-
- A: Next week. You missed the deadline. Tough, sucker.
-
- 18.12: Why don't C comments nest? How am I supposed to comment out
- code containing comments? Are comments legal inside quoted
- strings?
-
- A: We believe it has something to do with captivity; C comments in
- the wild mate and nest normally. The San Diego Zoo believes it
- has managed to convince some C comments to nest, but it's hard
- to tell how much of that is really in the preprocessor, and how
- much of it is just bovine fecal matter.
-
- 18.13: How can I get the ASCII value corresponding to a character, or
- vice versa?
-
- A: chr$(foo); You would have known this if you had an integer basic
- in ROM.
-
- 18.14: How can I implement sets and/or arrays of bits?
-
- A: With linked lists of bitfields. You may also wish to simply use a
- large set of constants and some clever use of the switch statement,
- i.e.:
-
- enum { zero, one, two, three };
-
- int bitwise_or(int n, int m) {
- switch (n) {
- case three:
- return three;
- break;
- case two:
- switch (m) {
- case one: case three: return three; break;
- default: return two; break;
- }
- break;
- case one:
- switch (m) {
- case two: case three: return three; break;
- default: return one; break;
- }
- break;
- default: case zero:
- switch (m) {
- case one: return one; break;
- case two: return two; break;
- case three: return three; break;
- case zero: default: return zero; break;
- }
- break;
- }
- }
-
- Obviously, you'll need to increase this slightly to deal with
- more than two bits. This is much more readable than the alleged
- ``C'' solution:
-
- int bitwise_or(int n,int m){return n|m;}
-
- Note how the lack of whitespace around operators obscures the
- functionality of the code. A clear argument for explicit
- statement of program logic over arcane operators, if I
- ever saw one.
-
- The enum at the top isn't declared ``const int'', because the
- resulting ``const poisoning'' would require casts during all of
- the switch statements.
-
- 18.15: What is the most efficient way to count the number of bits which
- are set in a value?
-
- A: Start a counter at zero and add one to it for each bit set. Some
- operating systems may provide a call to do this. For values over
- INT_MAX/2, start the counter at CHAR_BIT * sizeof(int) and subtract
- one for each bit not set.
-
- 18.16: How can I make this code more efficient?
-
- A: Remove the comments; the no-op instructions generated by comments
- can slow your code down signifigantly. Similarly, shorten variable
- names. Most compilers, to implement pass by value, actually pass
- the names of variables in the stack; shorter variable names will
- reduce stack usage, and consequently execution time. If your compiler
- has good loop optimization, replace
-
- foo();
-
- with
-
- do {
- foo();
- } while (1 != 1);
-
- which will likely receive more optimization.
-
- 18.17: Are pointers really faster than arrays? How much do function
- calls slow things down? Is ++i faster than i = i + 1?
-
- A: Yes. About 10 ms per call. Only on machines which feature
- preincrement addressing.
-
- 18.18: This program crashes before it even runs! (When single-stepping
- with a debugger, it dies before the first statement in main.)
-
- A: You probably declared main as ``void main(void)''. It's also possible
- that the first statement in main is abort(); - by the as if rule,
- the compiler can abort at any time before then, too. Some compilers
- have bugs, and will produce buggy code for any module which includes
- the letters ``a'', ``b'', ``o'', ``r'', and ``t'' in that order before
- the first function declaration.
-
- 18.19: What do ``Segmentation violation'' and ``Bus error'' mean?
-
- A: C programs are very territorial, and divide their code into
- segments. Violating these segments can trigger riots; similarly,
- pointers and integral constants are at the front of the bus,
- wheras arrays, strings, and other second-class data types are
- required to be at the rear of the bus. When they start forgetting
- their places, you can get a bus error. This is what the whole
- ``integral'' type thing is about - integrated bussing.
-
- 18.20: My program is crashing, apparently somewhere down inside malloc,
- but I can't see anything wrong with it.
-
- A: Your vendor's library is buggy; complain loudly. Don't send them
- any example code; they just ask for that so they can steal your
- trade secrets.
-
- 18.21: Does anyone have a C compiler test suite I can use?
-
- A: Yes. Unfortunately, it's probably broken. It's hard to tell.
-
- 18.22: Where can I get a YACC grammar for C?
-
- A: You can't; YACC is written in C.
-
- 18.23: I need code to parse and evaluate expressions.
-
- A: Ask any first year CS student. You may also wish to use your C
- compiler.
-
- 18.24: I need a sort of an ``approximate'' strcmp routine, for comparing
- two strings for close, but not necessarily exact, equality.
-
- A: Just try comparing pointers near the original pointers.
-
- 18.25: Will 2000 be a leap year?
-
- A: That's a hard question. I'd suggest using an encyclopedia, or
- possibly a dictionary - look up ``yes''.
-
- 18.26: How do you pronounce ``char''?
-
- A: Like the first word of ``char *''. The accent is generally on
- the first syllable.
-
- 18.27: Is this FAQ for real?
-
- A: *sigh* I knew someone would ask that. (Editorial note: I recieved
- several corrections to minor factual errors when I first posted this.)
-
- If you actually want to know something about C, get a good book
- (K&R is reccommended), and check out the real FAQ, which is posted
- monthly in comp.lang.c, and available by anonymous ftp from
- rtfm.mit.edu.
-
- I have a small web page of C stuff:
- http://www.solon.com/~seebs/c
- and there is an excellent site at Lysator:
- http://www.lysator.liu.se/c
-
- For extra credit, see if you can figure out what all of the examples
- really do; most of them will compile, and all of them can be gotten
- to compile with sufficient #defines. (I think.)
-
-
- Credits:
-
- The original comp.lang.c FAQ is maintained by Steve Summit, and
- many of the questions were stolen from it. Some of the idiotic
- misconceptions here are original, but many are from other sources.
- People have really said or advocated several of these; think about it.
- The Zork series may well be trademarked, but it was certainly
- an excellent game. Some of the mistakes may look similar to things
- warned against in _C Traps and Pitfalls_. And, of course, if
- Dennis Ritchie hadn't written C, these jokes would be much harder
- to understand.
-
- Several people have contributed answers or questions, but I have
- lost the names in the mists of time.
- --
- Peter Seebach - seebs@solon.com - Copyright 1996 Peter Seebach.
- C/Unix wizard -- C/Unix questions? Send mail for help. No, really!
- FUCK the communications decency act. Goddamned government. [literally.]
- The *other* C FAQ - http://www.solon.com/~seebs/c/c-iaq.html
-